#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>
namespace ns_protocol
{
//#define MYSELF 1

#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define SEP "\r\n"
#define SEP_LEN strlen(SEP)   //不能是sizeof

    class Request
    {
    public:
        // 1.自主实现 "x_ op y_"
        // 2.使用现成的方案
        std::string Serialize()
        {
#ifdef MYSELF
            std::string str;
            str = std::to_string(x_);
            str += SPACE;
            str += op_;
            str += SPACE;
            str += std::to_string(y_);
            return str;
#else
            //std::cout << "TODO" << std::endl;
            Json::Value root;
            root["x"] = x_;
            root["y"] = y_;
            root["op"] = op_;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        // "x_ op_ y_"
        // "1234+5678"
        bool Deserialized(const std::string &str)
        {
#ifdef MYSELF
            std::size_t left = str.find(SPACE);
            if (left == std::string::npos)
                return false;
            std::size_t right = str.rfind(SPACE);
            if (right == std::string::npos)
                return false;
            x_ = atoi(str.substr(0, left).c_str());
            y_ = atoi(str.substr(right + SPACE_LEN).c_str());
            if (left + SPACE_LEN > str.size())
                return false;
            else
                op_ = str[left + SPACE_LEN];
            return true;
#else
            //std::cout << "TODO" << std::endl;
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);    //将root的内容读到str里面
            x_ = root["x"].asInt();
            y_ = root["y"].asInt();
            op_ = root["op"].asInt();
            return true;
#endif
        }

    public:
        Request() {}
        Request(int x, int y, char op) : x_(x), y_(y), op_(op)
        {
        }
        ~Request() {}

    public:
        int x_;
        int y_;
        char op_;
    };

    class Response
    {
    public:
        //"code_ result_"
        std::string Serialize()
        {
#ifdef MYSELF
            std::string s;
            s = std::to_string(code_);
            s += SPACE;
            s += std::to_string(result_);
            return s;

#else
            //std::cout << "TODO" << std::endl;
            Json::Value root;
            root["code"] = code_;
            root["result"] = result_;
            root["xx"] = x_;
            root["yy"] = y_;
            root["zz"] = op_;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        /// " 111 100"
        bool Deserialized(const std::string &s)
        {
#ifdef MYSELF
            std::size_t pos = s.find(SPACE);
            if (pos == std::string::npos)
                return false;
            code_ = atoi(s.substr(0, pos).c_str());
            result_ = atoi(s.substr(pos + SPACE_LEN).c_str());
            return true;
#else
        //std::cout << "TODO" << std::endl;
        Json::Value root;
        Json::Reader reader;
        reader.parse(s, root);
        code_ = root["code"].asInt();
        result_ = root["result"].asInt();
        x_ = root["xx"].asInt();
        y_ = root["yy"].asInt();
        op_ = root["zz"].asInt();
        return true;          
#endif
        }

    public:
        Response(){}
        Response(int result, int code, int x, int y, char op)
        :result_(result),code_(code),x_(x),y_(y),op_(op)
        {}
        ~Response(){}


    public:
        int code_;    //计算结果
        int result_;   //计算结果的状态码

        int x_;
        int y_;
        char op_;
    };

    //临时方案
    //调整方案2：我们期望你必须给我返回一个完整的报文
    bool Recv(int sock, std::string *out)
    {
        //udp是面向数据包的, 发一个数据包，就一个数据包
        //tcp是面向字节流的，发字节流，怎么分割成一个包呢？
        //recv：你怎么保证，你读到的inbuffer，是一个完整的请求呢？不能保证
        // "1234 + 5678" : 1234 +
        // 我们写的单纯是无法解决问题的，需要对协议进行进一步定制
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer)-1, 0);   //9\r\n123+789\r\n
        if(s>0)
        {
            buffer[s] = 0;
            *out += buffer;
        }
        else if(s==0)
        {
            std::cout<<"client quit"<<std::endl;
            return false;
        }
        else
        {
            std::cout<<"recv error"<<std::endl;
            return false;
        }
        return true;
    }

    void Send(int sock, const std::string str)
    {
        int n = send(sock, str.c_str(), str.size(), 0);
        if(n<0)
        {
            std::cout<<"send error"<<std::endl;
        }
    }
    // "length\r\nx_ op_ y_\r\n..." // 10\r\nabc
    // "x_ op_ y_\r\n length\r\nXXX\r\n"
    std::string Decode(std::string &buffer)
    {
        std::size_t pos = buffer.find(SEP);
        if(pos==std::string::npos) return "";   //没有\r\n不做处理，返回空串
        int size = atoi(buffer.substr(0,pos).c_str());   //长度转化成int类型
        int surplus = buffer.size()-pos-2*SEP_LEN;
        if(surplus>=size)   //表示剩下的长度一定是一个合法的字符串，因为把东西都减没了
        {
            buffer.erase(0, pos+SEP_LEN);
            std::string s = buffer.substr(0, size);
            buffer.erase(0, size+SEP_LEN);
            return s;
        }
        else return "";
    }

    std::string Encode(std::string &s)
    {
        std::string new_package = std::to_string(s.size());
        new_package+=SEP;
        new_package+=s;
        new_package+=SEP;
        return new_package;
    }

}